#!/usr/bin/env ruby

module GridObserver
  def initialize
    @sight_listeners = []
    @sound_listeners = []
    @smell_listeners = []
    @touch_listeners = []
    @sense_listeners = []
  end
  
  #
  # Register/Unregister Oberservers
  #
  
  def register_sight_listener(&blk)
    @sight_listeners << blk
  end
  
  def unregister_sight_listener(&blk)
    @sight_listeners.remove(blk)
  end
  
  def register_sound_listener(&blk)
    @sound_listeners << blk
  end
  
  def unregister_sound_listener(&blk)
    @sound_listeners.remove(blk)
  end
  
  def register_smell_listener(&blk)
    @smell_listeners << blk
  end
  
  def unregister_smell_listener(&blk)
    @smell_listeners.remove(blk)
  end
  
  def register_touch_listener(&blk)
    @touch_listeners << blk
  end
  
  def unregister_touch_listener(&blk)
    @touch_listeners.remove(blk)
  end
  
  def register_sense_listener(&blk)
    @sense_listeners << blk
  end
  
  def unregister_sense_listener(&blk)
    @sense_listeners.remove(blk)
  end
  
  protected
  
  #
  # Notify Observers
  #
  
  def notify_sight_listeners(event)
    @sight_listeners.each {|listener| listener.call(event)}
  end
  
  def notify_sound_listeners(event)
    @sound_listeners.each {|listener| listener.call(event)}
  end
  
  def notify_smell_listeners(event)
    @smell_listeners.each {|listener| listener.call(event)}
  end
  
  def notify_touch_listeners(event)
    @touch_listeners.each {|listener| listener.call(event)}
  end
  
  def notify_sense_listeners(event)
    @sense_listeners.each {|listener| listener.call(event)}
  end
end

module SightListener
  
  def register_as_sight_listener(observable)
    if observable.respond_to?("each") then
      observable.each {|o| o.register_sight_listener {|event| self.sight_event(event)}}
    else
      observable.register_sight_listener {|event| self.sight_event(event)}
    end
  end
  
  protected
  
  def sight_event(event)
    puts "Warning: Event Unimplemented"
  end
end

module SoundListener
  
  def register_as_sound_listener(observable)
    if observable.respond_to?("each") then
      observable.each {|o| o.register_sound_listener {|event| self.sound_event(event)}}
    else
      observable.register_sound_listener {|event| self.sound_event(event)}
    end
  end
  
  protected
  
  def sound_event(event)
    puts "Warning: Event Unimplemented"
  end
end

module SmellListener
  
  def register_as_smell_listener(observable)
    if observable.respond_to?("each") then
      observable.each {|o| o.register_smell_listener {|event| self.smell_event(event)}}
    else
      observable.register_smell_listener {|event| self.smell_event(event)}
    end
  end
  
  protected
  
  def smell_event(event)
    puts "Warning: Event Unimplemented"
  end
end

module TouchListener
  
  def register_as_touch_listener(observable)
    if observable.respond_to?("each") then
      observable.each {|o| o.register_touch_listener {|event| self.touch_event(event)}}
    else
      observable.register_touch_listener {|event| self.touch_event(event)}
    end
  end
  
  protected
  
  def touch_event(event)
    puts "Warning: Event Unimplemented"
  end
end

module SenseListener
  
  def register_as_sense_listener(observable)
    if observable.respond_to?("each") then
      observable.each {|o| o.register_sense_listener {|event| self.sense_event(event)}}
    else
      observable.register_sense_listener {|event| self.sense_event(event)}
    end
  end
  
  protected
  
  def sense_event(event)
    puts "Warning: Event Unimplemented"
  end
end

class GridEvent
  
  SIGHT="SIGHT"
  SOUND="SOUND"
  SMELL="SMELL"
  TOUCH="TOUCH"
  SENSE="SENSE"
  
  attr_accessor :type 
  
  def initialize(type) 
    @type = type
  end
end